/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package megachess.svn;

import java.io.*;
import java.nio.charset.Charset;
import java.util.*;

/**
 *
 * @author johannes
 */
public class Board implements Cloneable{
    
    String filepath = "C:/Users/johannes/Documents/Fachhochschule/Projektarbeit Vorlesungsplan/netbeans/minichessboard.txt";
    char[][] board;
    int moveNum=1;
    char onMove='W';
    char status='?';
    
    //int sumValueBlack=0;
    //int sumValueWhite=0;
    int score=0;
    Hashtable heuristic = new Hashtable();
    
  
    
    
    public void createHeuristic(){
        heuristic.put('Q', 100);
        heuristic.put('R', 50);
        heuristic.put('N', 30);
        heuristic.put('B', 30);
        heuristic.put('P', 10);
        heuristic.put('K', 10000);
       
        heuristic.put('k', 10000);
        heuristic.put('q', 100);
        heuristic.put('r', 50);
        heuristic.put('n', 30);
        heuristic.put('b', 30);
        heuristic.put('p', 10);     
        
        
        calculateHeuristic();
    }//endmethod

  
    
    //creates Initial Board
    public Board (){
       
       
       
       board = new char [7] [6]; 
       
       board[1][1] = 'R';
       board[1][2] = 'N';
       board[1][3] = 'B';
       board[1][4] = 'Q';
       board[1][5] = 'K';
       board[2][1] = 'P';
       board[2][2] = 'P';
       board[2][3] = 'P';
       board[2][4] = 'P';
       board[2][5] = 'P';
       
       for(int line = 3;line<5;line++)
       {
           for(int column= 5; column>=0;column--)
           {
               board[line][column]='-';
           }
       }
       
       board[5][1] = 'p';
       board[5][2] = 'p';
       board[5][3] = 'p';
       board[5][4] = 'p';
       board[5][5] = 'p';
       board[6][1] = 'k';
       board[6][2] = 'q';
       board[6][3] = 'b';
       board[6][4] = 'n';
       board[6][5] = 'r';
        createHeuristic();
    }
    
    //Create a board from a String (Beginning with line 6 column 1, line 6 column2,....)
    public Board(String boardstring){
        Board(boardstring);
    }//end constructor
    
    public Board(String boardstring, char onMove, int moveNum)
    {
        Board(boardstring);
        this.onMove=onMove;
        this.moveNum=moveNum;
    }//endmethod
    
    
    public void Board(String boardstring)
    {
         board = new char [7] [6]; 
        char[] boardchar = boardstring.toCharArray();
        int counter = 0;
        
        for (int line = 6; line>=1; line--)
        {
          for (int column = 1; column<=5; column++)
          {
              board[line][column]=boardchar[counter];
              counter++;
              
          }//endfor
        }//endfor  
        //toCommandLine();
        
        
        
        createHeuristic();
        
        
    }//endmethod

    public Hashtable getHeuristic() {
        return heuristic;
    }

    public char getStatus() {
        return status;
    }
    
    
    

    public Board(Board originalBoard)
    {
            
        this.moveNum=originalBoard.getMoveNum();
        this.onMove=originalBoard.getOnMove();
        this.board=new char [7][6];
        
        for (int zeile=1; zeile<=6; zeile++)
                {
                    for (int spalte=1;spalte<=5;spalte++)
                    {
                        this.board[zeile][spalte]=originalBoard.board[zeile][spalte];
                    }//endfor
                }//endfor
        
        this.heuristic=originalBoard.getHeuristic();
        this.score=originalBoard.score;
                //createHeuristic();
        //System.out.println(this.board[1][1]);
    }//end method
    
  
    //Create Board from File
    public void BoardfromInputStream(){
        
        String s="";
        String ss="";
        
        try{
            
            Reader reader = new FileReader(filepath);
            BufferedReader br = new BufferedReader(reader);
            
            while ((s=br.readLine())!=null)
            {
                ss+=s;
            }
            
        }catch (Exception ex)
        {
            System.out.println(ex.toString());
        }//entry
        
        
        Board(ss);
        //System.out.println(s);
    }//endfromInputStream
 

    
    public int getMoveNum() {
        return moveNum;
    }

    public char getOnMove() {
        return onMove;
    }
     
    public String toString(boolean zeilenumbruch){

        String output="";
        
        for (int line = 6; line>0; line--)
        {
        
          
          for (int column = 1; column<6; column++)
          {
              output+=board[line][column];
              
              if(column==5 && zeilenumbruch==true)
              {
                  output+="\n";
                  
              }//endif
              
              
              
          }//endfor
        }//endfor
        return output;
    }//end method toOutputString
    
    
    //write Board into File
    public void printToOutputStream()
    {
        String message = toString(false);
        //String message = new StringBuffer(toOutputString(false)).reverse().toString();
        
        
        try{
            FileOutputStream fos = new FileOutputStream(filepath);        
            fos.write(message.getBytes(Charset.forName("UTF-8")));
        }
        
        catch (Exception ex)
        {
            System.out.println(ex.toString());
        }//entry
    }//endtoOutputStream
     
    
    
    //write Board to Comandline
    public void toCommandLine(){
        
       // System.out.println("Now on Move: " + onMove);
        System.out.println(toString(true));
        System.out.println("next Move: " + onMove);
        System.out.println("Move Number: " + moveNum);
        System.out.println("*****************************");
        
    }//endtoCommandLine
    
    //
    public char move(String smove)
    {
      if(smove.length()!=5)
      {
          System.out.println("String should be 5 digits long! \n You entered: " + smove );
          return 'X';
      }
      else{
            String from, to;

            from = smove.substring(0, 2);
            to   = smove.substring(3, 5);

            Square objfrom = new Square(from);
            Square objto   = new Square(to);

            return move(objfrom, objto);
      }//endif-else
    }//endmove
    
    public char move(Move mymove){
        return move(mymove.getFromSquare(), mymove.getToSquare());
    }//endmethod
    //
    public char move(Square from, Square to)
    {
        
        char tempfigure= ' ';
        boolean movevalid=false;
        ArrayList<Move> possibleMoves = moveList(from);
        
        //check if move is a valid move from the movelist
        for(Move m : possibleMoves){
            if((m.getToSquare().getRow()==to.getRow()) && (m.getToSquare().getCol()==to.getCol()))
                movevalid = true;
        }//endfor
        
        //player white can only move white figures
        if(movevalid== true)
        {
            Figure curentfigure = new Figure(board[from.getRow()][from.getCol()]);
            if(curentfigure.getColor()!=onMove)
                movevalid=false;
        }//endif
        
        if(movevalid == true){
            //check if black or white has won
            tempfigure=board[to.getRow()][to.getCol()];
            if(tempfigure=='K')
                status='B';
            if (tempfigure=='k')
                status='W';
            
            
            board[to.getRow()][to.getCol()]=board[from.getRow()][from.getCol()];
            board[from.getRow()][from.getCol()]='-';
            
            updateHeuristic(new Figure(tempfigure), true);
            
            //if a pawn gets to the foreign edge he will be replayced by a Queen
            if((to.getRow()==1) &&(board[to.getRow()][to.getCol()]=='p')){
                board[to.getRow()][to.getCol()]='q';
                updateHeuristic(new Figure('p'), true);
                updateHeuristic(new Figure('q'), false);
            }//endif
            if((to.getRow()==6) &&(board[to.getRow()][to.getCol()]=='P')){
                board[to.getRow()][to.getCol()]='Q';
                updateHeuristic(new Figure('P'), true);
                updateHeuristic(new Figure('Q'), false);
            }//endif
               
               
            
            if(onMove=='W')
                onMove='B';
            else
            {    
                onMove='W';
                moveNum++;
            }//endelse
            
            if((status=='B')||(status=='W'))
                return status;
            else if(moveNum>=41)
                return '=';
            else 
                return '?';
                
                
               
        }else{
            //Move not valid!!!!
            System.out.println("Move is not valid. Please try again.");
            return 'X';
        }//endif

    }//endmove
    

    
       
    public ArrayList<Move> scan(Square initialSquare,int moveX, int moveY, boolean capture, boolean stopshort){
        ArrayList<Move> moves = new ArrayList<Move>();  
        
                
        Figure initialFigure=new Figure(board[initialSquare.getRow()][initialSquare.getCol()]);
        char color =initialFigure.getColor();
        
        
        int x = initialSquare.getCol();
        int y = initialSquare.getRow();
        int yinitial=y;
        int xinitial=x;
        
        //Square targetSquare = new Square(x, y);
        Figure targetFigure;
        Square targetSquare;
        int targetHeuristic=0;
       //if the initial Field doesn't contain a figure....skip    
        
        if (initialFigure.isFigure()==true)
        {
                do{
                    
                    //#######################################
                    
                    
                    x+=moveX;
                    y+=moveY;
                    
                    //############################################
                targetSquare = new Square(x,y);

                if(x>5 || x<1 || y>6 || y<1)
                {
                    //System.out.println("--Out of Field");
                    break;
                }//endif
                targetFigure = new Figure(board[y][x]);

                //is there a figure on the targetfield?
                if(targetFigure.isFigure())
                {
                    //has the figure on the targetfield the same color?
                    if(targetFigure.getColor()==initialFigure.getColor())
                    {
                       // System.out.println("--Target Figure has the same Color");
                        break;
                    }//endif

                    //Can the targetfigure be captured?
                    if(capture==false)
                    {
                           // System.out.println("--capture = false");
                        break;

                    }//endif

                    stopshort=true;
                    //dests.add(targetSquare);
                    
                    targetHeuristic=(int)heuristic.get(targetFigure.getName());
                   // moves.add(new Move(new Square(xinitial, yinitial),targetSquare,targetHeuristic));
                  }
                //endif Figure on targetFiled
                    
                    
                moves.add(new Move(new Square(xinitial, yinitial),targetSquare,targetHeuristic));
                
                }while(stopshort==false);
        }//end if initial field has figure
        else
        {
            System.out.println("--No Figure on initial Field");
        }
            
       // System.out.println("Anzahl moves: " + moves.size());
        
        //for (Move m : moves)
           // m.printMove();
        
        return moves;
    }//endmethod ArrayList
    
  public ArrayList<Move> moveList(Square initialSquare)
  {
      char p =board[initialSquare.getRow()][initialSquare.getCol()];
      ArrayList<Move> moves = new ArrayList<Move>();
      int dx, dy, temp;
      boolean stopshort=false ;
      boolean capture=true;
      //King and Queen
      if((p=='q') || (p=='Q') || (p=='k') || (p=='K')){
          
          for(dx=-1;dx<=1;dx++){
                     for(dy=-1;dy<=1;dy++){
                         if(dx==0 && dy==0)
                             continue;
                          if((p=='k') || (p=='K'))
                                moves= mergeArrayLists(moves, scan(initialSquare, dx, dy, true, true));
                          else
                                moves= mergeArrayLists(moves, scan(initialSquare, dx, dy, true, false));
                     }//endfor
          }//endfor 
          return moves;
      }else if((p=='b') || (p=='B') || (p=='r') || (p=='R')){
          //Bishop and Rook
          dx=1;
          dy=0;
          if((p=='b') || (p=='B'))
          {
          stopshort=true; 
          capture=false;
          }//endif 
          
            
          for(int i=1;i<5;i++){
              moves= mergeArrayLists(moves, scan(initialSquare, dx, dy, capture, stopshort));
              temp = dy;
              dy = dx;
              dx = temp;
              dy = dy * (-1);
              //System.out.println(dx + ":" + dy);
          }//endfor
          
          if((p=='b') || (p=='B')){
               dx=1;
               dy=1;
               stopshort=false;
               capture=true;
                for(int j=1;j<5;j++){
                moves= mergeArrayLists(moves, scan(initialSquare, dx, dy, capture, stopshort));    
                temp = dy;
                dy = dx;
                dx = temp;
                dy=dy*(-1);
                }//endfor
          }//endif
      return moves;             
     
      }else if ((p=='n') || (p=='N')) {
          dx=1;
          dy=2;
          stopshort=true;
          for(int k=1;k<5;k++){
              moves= mergeArrayLists(moves, scan(initialSquare, dx, dy, capture, stopshort));
              temp = dy;
              dy = dx;
              dx = temp;
              dy=dy*(-1);
          }///endfor
          dx=-1;
          dy=2;
          for(int l=1;l<5;l++){
              moves= mergeArrayLists(moves, scan(initialSquare, dx, dy, capture, stopshort));
              temp = dy;
              dy = dx;
              dx = temp;
              dy=dy*(-1);
          }//endfor
          return moves;
      }else if((p=='p') || (p=='P')){
          int dir = 1;
          if(new Figure(p).getColor()=='B')
              dir = -1;
          stopshort=true;
          
          
          ArrayList<Move> m = scan(initialSquare, -1, dir, capture, stopshort);
          if ((m.size() == 1) && (isCapture(m.get(0))))
                  moves = mergeArrayLists(moves, m);
          
          m = scan(initialSquare, 1, dir, capture, stopshort);
          if ((m.size() == 1) && (isCapture(m.get(0))))
                  moves = mergeArrayLists(moves, m);
                  
                  capture=false;
                  moves = mergeArrayLists(moves, scan(initialSquare, 0, dir, capture, stopshort));
                  return moves;
 
      }else
          return null;
  
  }//end method    
  
  public boolean isCapture (Move capture){
      Square fromSquare= capture.getFromSquare();
      Square toSquare = capture.getToSquare();
      
      Figure fromFigure= new Figure (board[fromSquare.getRow()][fromSquare.getCol()]);
      Figure toFigure= new Figure (board[toSquare.getRow()][toSquare.getCol()]);
      //System.out.println("From color: " + fromFigure.getColor());
      //System.out.println("To color: " + toFigure.getColor());
      
        if(fromFigure.getColor()==toFigure.getColor() || (toFigure.getColor()=='-'))
        {
            //capture.printMove() ;
            //System.out.println(" isCapture: false");
            return false;
        }else
        {   
           // capture.printMove() ;
           // System.out.println("isCapture: true");
            return true;      
        }//endif
      
  }//endmethod
  
  public ArrayList<Move> getAllMoves()
  {
      ArrayList<Move> moves= new ArrayList<Move>();
    for (int row = 1; row <=6; row++)
        {
            for (int col = 1; col <=5; col++)
            {
                if (onMove== (new Figure(board[row][col])).getColor())
                {
                    moves= mergeArrayLists(moves, moveList(new Square(col, row)));
                }//endif
           
            
            }//end for
        }//endfor
        
    return moves;
  }
 
  public void printStatusReport(){
      if (status=='W')
          System.out.println("-->White wins");
      else if (status=='B')
          System.out.println("-->Black wins");
      else if (status=='?')
          System.out.println("-->Game is still running");
      else if (status=='=')
          System.out.println("-->Game ends in a draw");
      else
          System.out.println("-->An error occured");      
  }//endmethod
  
  private ArrayList<Move> mergeArrayLists(ArrayList<Move> list1, ArrayList<Move> list2)
  {
      for (Move m : list1)
          list2.add(m);
  
          return list2;
  }//end method
  
  public void calculateHeuristic(){
         score=0;   
      Figure currentFigure=null;

      for(int row=1;row<7;row++){
          for(int col=1;col<6;col++)
          {
           currentFigure = new Figure(board[row][col]);   
              
              if(currentFigure.getColor()=='B')
              {
                  score-=(int)heuristic.get(currentFigure.getName());
                  //sumValueBlack+=(int)heuristic.get(currentFigure.getName());
              }else if(currentFigure.getColor()=='W')
              {
                  score+=(int)heuristic.get(currentFigure.getName());
                   //sumValueWhite+=(int)heuristic.get(currentFigure.getName());
              }//endif
          }//endfor
      }//endfor
   //   System.out.println("Score of Board: " + score);
      
  }//endmethod

    public int getScore()
    {
        if (onMove=='B')
            return -score ;
        
        return score;
    }
  
  public void updateHeuristic(Figure targetfigure, boolean capture){
      //System.out.println("updateHeuristic: " + targetfigure.getName() + ", " + capture);
      int factor = 1;
      
      if(capture==true)
          factor =-1;
            
      if(targetfigure.getColor()=='W'){
          score+=factor*((int)heuristic.get(targetfigure.getName()));
          //sumValueWhite+=factor*((int)heuristic.get(targetfigure.getName()));
      }else if(targetfigure.getColor()=='B'){
          score+=factor*(-1)*((int)heuristic.get(targetfigure.getName()));
          //sumValueBlack+=factor*((int)heuristic.get(targetfigure.getName()));
      }//endif
      
      //System.out.println("score end updateHeuristic:" + score);
  }//endmethod
  
  public void copyBoard(){
      char[][] copyBoard = new char[7][6];
      
      for(int row=1;row<7;row++){
          for(int col=1;col<6;col++){
              copyBoard[row][col]=board[row][col];
          }//endfor
      }//endfor
      
  }//endmethod
  
}//endclass